#include "stdafx.h"
#include "TypeANCU.h"

TypeANCU::TypeANCU():
GeneralNCU(TypeA), m_currentSill(0)
{
}
TypeANCU::TypeANCU(const unsigned int &config):
GeneralNCU(TypeA,config), m_currentSill(0)
{
	if ( check(config) ) // check if config >= 1000
	{
        nSequence(config);
	}
	else
		errMsg = msg[0];
}
TypeANCU::TypeANCU(const unsigned int &config,
				   const vector<double> &paras):
GeneralNCU(TypeA, config), m_currentSill(0)
{
	if ( check(config) )
	{
        parameters(paras);
	}
	else
		errMsg = msg[0];
}
TypeANCU::TypeANCU(const TypeANCU &rhs):
GeneralNCU(rhs), m_initialSill(rhs.m_initialSill),
m_seq(rhs.m_seq), m_currentSill(rhs.m_currentSill)
{
}
TypeANCU& TypeANCU::operator=(const TypeANCU &rhs)
{
	if ( this != &rhs)
	{
		GeneralNCU::operator =(rhs);
		m_initialSill = rhs.m_initialSill;
		m_currentSill = rhs.m_currentSill;
        m_seq = rhs.m_seq;
	}
	return (*this);
}
TypeANCU::~TypeANCU()
{
}
/*********************************************
	Configuration Section
*********************************************/
// get the number of parameters of a NCU
const unsigned int TypeANCU::number() const
{
	return ((2*m_seq.number())+1);
}

// assign the number of composite vents in a NCU
void TypeANCU::nSequence(const unsigned int num)
{
	if ( check(num) )
	{
        m_seq.number(num);
		m_label.numCV(num);
	}
	else
		errMsg = msg[0];
}
void TypeANCU::reset()
{
	currentSill( m_initialSill);
}
/**********************************************
	Composite Vent Section
***********************************************/
bool TypeANCU::sequence(const vector<double> &paras)
{
	if ( !nSequence() )
		return false;
	else
	{
		m_seq.parameters(paras);
		return true;
	}
}
// get composite vents
const CVSequence& TypeANCU::sequence() const
{
	return m_seq;
}
// get the number of composite vents
unsigned int TypeANCU::nSequence() const
{
	return m_seq.number();
}
/*********************************************
	Parameters Section
*********************************************/
// assign all parametrs of a NCU
bool TypeANCU::parameters(const vector<double> &paras)
{
	if ( !number() )
	{
		errMsg = msg[1];
		return false;
	}
	if ( paras.size() != number() )
	{
		errMsg = msg[2];
		return false;
	}
	else
	{
		vector<double>::const_iterator iter = paras.begin();
		m_initialSill = *iter;
		reset(); // set the value of the current sill to the value of the initial sill
		 ++ iter;
		vector<double> tmp(iter, paras.end());
		m_seq.parameters(tmp);
		return true;
	}
}
// get all parameters of a NCU
vector<double> TypeANCU::parameters() const
{
	vector<double> paras, tmp;
    paras.push_back(m_initialSill);
	tmp = m_seq.parameters();
	paras.insert(paras.end(), tmp.begin(), tmp.end()); // modified on 14/06/2006
	return paras;
}
/*********************************************
Sill Section
*********************************************/	
void TypeANCU::initialSill(const double &IS)
{
	m_initialSill = IS;
	currentSill(IS);
}
const double& TypeANCU::initialSill() const
{
	return m_initialSill;
}
// virtual constructor
GeneralNCU* TypeANCU::clone() const
{
	return new TypeANCU(*this);
}
// get the genome information
vector<const GenomeType*> TypeANCU::genome() const
{
	vector<const GenomeType*> tmp;
	// insert the initial sill into the genome set
	tmp.push_back( &genomeSet().GetSillGenome() );
	// insert the composite vent into the genome set
	for (unsigned int i = 0 ; i < nSequence(); ++ i)
	{
		tmp.push_back( &genomeSet().GetVentGenome() );
		tmp.push_back( &genomeSet().GetSillGenome() );
	}
	return tmp;
}
// simulation
outputPair TypeANCU::simulation(const double &input)
{
	update(input);
	outputPair flow;
	flow.first = output(currentSill());
	flow.second = bottom(currentSill());
	// update the current sill
	currentSill(
		currentSill() - flow.first
		);
	return flow;
}
// calculate the output of the composite vent
double TypeANCU::output(const double &sill)
{
	return m_seq.output(sill);
}
	// calculate the output of the longitudinal outputs
inline double TypeANCU::bottom(const double &sill)
{
	return 0;
}
// update the current sill
// Recovery Function
void TypeANCU::update(const double &input)
{
#ifdef _NEW_RULE_OF_BASEFLOW
	if ( currentSill() < m_initialSill )
	{
		currentSill(m_initialSill);
	}
#endif
	if ( input >= 0 )
		IncCurrentSill(input);
}
bool TypeANCU::check(const unsigned int &num)
{
	if ( num < 1000 )
		return true;
	return false;
}

void TypeANCU::currentSill(const double &sill)
{
	m_currentSill = sill;
}
const double& TypeANCU::currentSill() const
{
	return m_currentSill;
}
void TypeANCU::IncCurrentSill(const double &increment)
{
	m_currentSill += increment;
}